\documentclass[12pt]{article}
\usepackage{xeCJK}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{indentfirst}
\usepackage{listings}
\pagenumbering{gobble}
\usepackage{color}
\definecolor{light-gray}{gray}{0.95}
\usepackage[
colorlinks=true,
linkcolor=blue,
urlcolor=cyan,
]{hyperref}
\usepackage[
a3paper,
%landscape,
nohead,
margin=2cm
]{geometry}
\lstset{numbers=right,
numberstyle=\footnotesize,
breaklines=true,
backgroundcolor=\color{light-gray},
xleftmargin=\parindent,
tabsize=2,
numbersep=5pt}

\pagestyle{empty}
\setlength{\parskip}{1em}
\hypersetup{pageanchor=false}

\begin{document}

\title{BCID 一步到胃}
\date{\today}
\author{ldcc}
\maketitle

\section{源码开发}

\subsection{环境、配置}

BCID 仓库源部署在码云云端上，项目本身基于以太坊（Ethereum）。

搭建项目开发环境：
\begin{itemize}
    \item 一个分布式版本控制工具Git；
    \item 一个Go 语言编译器（1.12 版本或以上）;
    \item 一个C 语言编译器（gcc/g++/clang）。
\end{itemize}

配置本地项目源：
\begin{lstlisting}[language=bash]
    mkdir -p ~/repo/BCID/src/github.com/ethereum/
    cd ./src/github.com/ethereum/
    git clone https://gitee.com/BCID-Okey/BCID-ETHEREUM.git go-ethereum
    cd ./go-ethereum/
    git remote add ethereum https://github.com/ethereum/go-ethereum.git
\end{lstlisting}

\subsection{编译、部署}

以太坊项目环境与依赖都配置完成后对就可以开始 BCID 节点的编译与部署。

使用 make 编译以太坊节点程序：
\begin{lstlisting}[language=bash]
    make geth
\end{lstlisting}

编译后的程序可以在 \quad ./build/bin/ 中找到，现在可以使用 geth 进行部署了。

在本地部署一个测试节点：
\begin{lstlisting}[language=bash]
    ./build/bin/geth
\end{lstlisting}

一些geth 的常用选项：
\begin{itemize}
    \item console：启动一个能够与节点进行交互的 JavaScript-REPL
    \item --datadir：该节点运行所产生的数据，包括数据库（databases）、密钥储存库（keystore）等
    \item --syncmode：节点的同步模式，有三个可选项 "fast" "full" "light"
    \item --verbosity：显示日志级别，0:不显示, 1:错误, 2:警告, 3:普通（默认）, 4:调试, 5:详细
    \item --rpc/--ws：允许节点提供 HTTP-RPC/WS-RPC 服务（WS 指 web-socket）
    \item --rpcaddr/--wsaddr：HTTP-RPC/WS-RPC 服务器接听的地址（默认 "localhost"）
    \item --rpcport/--wsport：HTTP-RPC/WS-RPC 服务器接听的端口（默认8545）
    \item --rpcapi/--wsapi：开放 HTTP-RPC/WS-RPC 使用的 api（eth, okey, net, web3 \ldots）
    \item --rpccorsdomain：允许跨源请求的域（测试时可以用 "*"）
\end{itemize}

\newpage

\section{智能合约}

\subsection{什么是智能合约}

智能合约是指那些运行在区块链节点上的应用程序，一般意义上的智能合约均特指以太坊的智能合约程序。
那么以下如没有特指，我们所进行讨论的智能合约也均特指以太坊的智能合约。

当一份部署在区块链上的智能合约被调用时，合约的字节码会在链上通过一个叫作 EVM 的解释器所执行。
EVM 除了对字节码进行解释运行还需要将操作的结果保存到链上。
从这层意义上来讲，以太坊不过是 EVM 这个状态机上的一个运行时 STATE 而已。

你可以通过 make 得到这个 EVM 程序，使用它进行你的智能合约链下测试。
\begin{lstlisting}[language=bash]
    make evm
\end{lstlisting}

\subsection{Solidity}

Solidity 是一个将某个或数个符合某种语法的文本数据编译成能够被 EVM 解释的字节码或者汇编指令集
（这里的汇编是指 EVM 中所能执行的指令集，并非一般意义上的汇编语言）。
而这种正则语法一般我们叫做 Solidity 语言。

\subsection{LLL}

LLL 是另一种以太坊智能合约编程语言，是一种 lisp-like 编程语言。

LLL 编译后的汇编指令比 Solidity 消耗更少的燃料，但由于受众人群太少，该项目逐渐被废弃。

在 Constantinople 版本后 LLL 已完全停止维护。

\subsection{Serpent}

\newpage

\section{应用程序接口}

\subsection{JSON-RPC}

JSON-RPC 是一种无状态轻量级的 RPC 传输协议，BCID 下开放的所有 api 均使用这种协议对节点进行远程过程调用。

请求对象：
\begin{itemize}
    \item jsonrpc 2.0 后的新增字段，指示当前请求的 JSON-RPC 版本
    \item method 请求的方法
    \item params 请求的参数
    \item id 用于两个对象之间的关联上下文
\end{itemize}

响应对象：
\begin{itemize}
    \item jsonrpc 2.0 后的新增字段，指示当前请求的 JSON-RPC 版本
    \item result 返回的结果
    \item error 返回的错误
    \item id 用于两个对象之间的关联上下文
\end{itemize}

\subsection{RPC api}

这里的 RPC api 指的是某一个 BCID 节点开放出去的 api 集，为了使用这些 api，需要在启动节点时提供一些配置：
\begin{lstlisting}[language=bash]
    ./build/bin/geth --rpc --rpcapi 'some apis'
\end{lstlisting}

以太坊的 api 请看这里： \url{https://github.com/ethereum/wiki/wiki/JSON-RPC}。

% TODO begin mark
下面介绍 BCID 的 api：

%% okey_getImeiType
\textbf{okey\_getImeiType}

返回指定地址的设备类型信息，该值的有效范围是$0 < \mathcal{T} \le \mathrm{Num}(\mathbb{B}_{2})$：
\begin{itemize}
    \item $\mathcal{T} = 1$，该设备为 O-Key 设备；
    \item $\mathcal{T} = 2$，该设备为门锁设备；
    \item $\dots$，有待补充。
\end{itemize}

参数：
\begin{itemize}
    \item 1. $String \in \mathbb{B}_{20}$ - 相关设备的账户地址；
    \item 2. $Number \mid String$ - 整形的区块数字，或者区块的字符串标签（"latest"，"earliest"，"pending"）。
\end{itemize}

返回：
\begin{itemize}
    \item Number - 设备的类型常数。
\end{itemize}

例子：
\begin{lstlisting}[language=bash]
    # request
    > curl -H 'Content-Type: application/json' --data '
    {
      "jsonrpc":"2.0",
      "id":1,
      "method":"okey_getImeiType",
      "params":["0x42ff6b5f7973d4303804ac65294737f713596a35","latest"]
    }' http://localhost:8545
    # response
    {
      "jsonrpc":"2.0",
      "id":1,
      "result":1
    }
\end{lstlisting}

\vskip1.2cm
\hrule
\vskip1.2cm

%% okey_getImei
\textbf{okey\_getImei}

返回指定地址的设备 IMEI 信息，一个 IMEI 是一个大小为 32 字节的哈希字符串，它的第 1 个字节总是表示为该设备的设备类型。

参数：
\begin{itemize}
    \item 1. $String \in \mathbb{B}_{20}$ - 相关设备的账户地址；
    \item 2. $Number \mid String$ - 整形的区块数字，或者区块的字符串标签（"latest"，"earliest"，"pending"）。
\end{itemize}

返回：
\begin{itemize}
    \item $String \in \mathbb{B}_{32}$ - 设备 IMEI 的 Keccak256 哈希值。
\end{itemize}

例子：
\begin{lstlisting}[language=bash]
    # request
    > curl -H 'Content-Type: application/json' --data '
    {
      "jsonrpc":"2.0",
      "id":2,
      "method":"okey_getImei",
      "params":["0x42ff6b5f7973d4303804ac65294737f713596a35","latest"]
    }' http://localhost:8545
    # response
    {
      "jsonrpc":"2.0",
      "id":2,
      "result":"0x0144bb55167ab332117049e2ccd3d8863d241bcc80f46302310a6d942a90e851"
    }
\end{lstlisting}

\vskip1.2cm
\hrule
\vskip1.2cm

%% okey_getCertificate
\textbf{okey\_getCertificate}

返回指定地址的设备证书信息，返回的结果并非一个完整的证书数据，而是该证书的 Keccak256 哈希值。

参数：
\begin{itemize}
    \item 1. $String \in \mathbb{B}_{20}$ - 相关设备的账户地址；
    \item 2. $Number \mid String$ - 整形的区块数字，或者区块的字符串标签（"latest"，"earliest"，"pending"）。
\end{itemize}

返回：
\begin{itemize}
    \item $String \in \mathbb{B}_{32}$ - 设备证书的 Keccak256 哈希值。
\end{itemize}

例子：
\begin{lstlisting}[language=bash]
    # request
    > curl -H 'Content-Type: application/json' --data '
    {
      "jsonrpc":"2.0",
      "id":3,
      "method":"okey_getCertificate",
      "params":["0x42ff6b5f7973d4303804ac65294737f713596a35","latest"]
    }' http://localhost:8545
    # response
    {
      "jsonrpc":"2.0",
      "id":3,
      "result":"0xce00473e3518f320ba6283b673d54b570b74d2185a9ae390563ad5847a91b84e"
    }
\end{lstlisting}


\vskip1.2cm
\hrule
\vskip1.2cm

%% okey_getBalance
\textbf{okey\_getBalance}

返回指定地址指示设备的所有隐私信息。

参数：
\begin{itemize}
    \item 1. $String \in \mathbb{B}_{20}$ - 相关设备的账户地址；
    \item 2. $Number \mid String$ - 整形的区块数字，或者区块的字符串标签（"latest"，"earliest"，"pending"）。
\end{itemize}

返回：
\begin{itemize}
    \item $JSON: \{P \mid P \in (\mathbb{B}_{20} , \mathbb{B}_{32})\}$ - 设备隐私的键值对数据。
\end{itemize}

例子：
\begin{lstlisting}[language=bash]
    # request
    > curl -H 'Content-Type: application/json' --data '
    {
      "jsonrpc":"2.0",
      "id":4,
      "method":"okey_getBalance",
      "params":["0x42ff6b5f7973d4303804ac65294737f713596a35","latest"]
    }' http://localhost:8545
    # response
    {
      "jsonrpc":"2.0",
      "id":4,
      "result":{
        "0xa87a3f428d0032b003cf2d7bfa542efbe28c5800":
        "0x87663e8c7ccfc81539af1833b1e482d9211926a752984665ad92c03dd30f5e38"
      }
    }
\end{lstlisting}

\vskip1.2cm
\hrule
\vskip1.2cm

%% okey_bindImei
\textbf{okey\_bindImei}

对指定地址的设备绑定 IMEI 与 证书 等相关信息，如果该地址指向一个空账号则创建一个账号再进行绑定。

参数：
\begin{itemize}
    \item 1. $String \in \mathbb{B}_{20}$ - 相关设备的账户地址；
    \item 2. $String \in \mathbb{B}_{32}$ - 绑定 IMEI 的 Keccak256 哈希值；
    \item 3. $String \in \mathbb{B}_{32}$ - 绑定证书的 Keccak256 哈希值。
\end{itemize}

返回：
\begin{itemize}
    \item $String \in \mathbb{B}_{32}$ - 该交易的唯一哈希值，当该交易不合法时将返回空的哈希值（$\mathcal{T}_e \in \mathbb{N}_{32}$）。
\end{itemize}

例子：
\begin{lstlisting}[language=bash]
    # request
    > curl -H 'Content-Type: application/json' --data '
    {
      "jsonrpc":"2.0",
      "id":5,
      "method":"okey_bindImei",
      "params":[
        "0x77dfe620dd9f88ad12f8d073f2157bebf8c62c52",
        "0x01dc3bb54c7e738bcd13b6f804059c5642571b6c14b7ebff6e1ee78daaf2de10",
        "0x7c1b16802b304761acd81e033c1db5a9721da4b32959e4a8361983cfacacbbec"
      ]
    }' http://localhost:8545
    # response
    {
      "jsonrpc":"2.0",
      "id":5,
      "result":"0xfd10194c2687971641e46f54762686636295c97eabe7de4a64aeed0955968d5f"
    }
\end{lstlisting}

\vskip1.2cm
\hrule
\vskip1.2cm

%% okey_applyPrivacy
\textbf{okey\_applyPrivacy}

对指定地址的设备绑定一份隐私数据。

如果绑定的对象是 O-Key 设备，则该份数据表示为你的生物信息，如指纹、人脸特征值、DNA 等原始数据的哈希值；
如果绑定的对象门锁设备，则该份数据表示为某个 O-Key 设备的账号地址；
后续设备有待补充。

参数：
\begin{itemize}
    \item 1. $String \in \mathbb{B}_{20}$ - 相关设备的账户地址；
    \item 2. $String \in \mathbb{B}_{32}$ - 相关 IMEI 的 Keccak256 哈希值；
    \item 3. $String \in \mathbb{B}_{32}$ - 相关证书的 Keccak256 哈希值；
    \item 4. $String \in \mathbb{B}_{20}$ - 绑定隐私信息的 Keccak256 哈希值。
\end{itemize}

返回：
\begin{itemize}
    \item $String \in \mathbb{B}_{32}$ - 该交易的唯一哈希值，当该交易不合法时将返回空的哈希值（$\mathcal{T}_e \in \mathbb{N}_{32}$）。
\end{itemize}

例子：
\begin{lstlisting}[language=bash]
    # request
    > curl -H 'Content-Type: application/json' --data '
    {
      "jsonrpc":"2.0",
      "id":6,
      "method":"okey_applyPrivacy",
      "params":[
        "0x77dfe620dd9f88ad12f8d073f2157bebf8c62c52",
        "0xa87a3f428d0032b003cf2d7bfa542efbe28c5800",
        "0x01dc3bb54c7e738bcd13b6f804059c5642571b6c14b7ebff6e1ee78daaf2de10",
        "0x7c1b16802b304761acd81e033c1db5a9721da4b32959e4a8361983cfacacbbec"
      ]
    }' http://localhost:8545
    # response
    {
      "jsonrpc":"2.0",
      "id":6,
      "result":"0x6134f31a6778c568b1f1272385de5a2c894c8a1bf7d14c0aae015e65850649b5"
    }
\end{lstlisting}

\vskip1.2cm
\hrule
\vskip1.2cm

%%% okey_copy
%\textbf{okey\_copy}
%
%TODO
%
%\vskip1.2cm
%\hrule
%\vskip1.2cm

%% okey_transfer
\textbf{okey\_transfer}

转移一份隐私数据给其它设备，该操作需要两件设备具有相同类型。

参数：
\begin{itemize}
    \item $from:String \in \mathbb{B}_{20}$ - 发送对象的账户地址；
    \item $to:String \in \mathbb{B}_{20}$ - 接收对象的账户地址；
    \item $imei:String \in \mathbb{B}_{32}$ - 发送对象 IMEI 的 Keccak256 哈希值；
    \item $cert:String \in \mathbb{B}_{32}$ - 发送对象证书的 Keccak256 哈希值；
    \item $adimei:String \in \mathbb{B}_{32}$ - 接收对象 IMEI 的 Keccak256 哈希值；
    \item $adcert:String \in \mathbb{B}_{32}$ - 接收对象证书的 Keccak256 哈希值；
    \item $priv:String \in \mathbb{B}_{20}$ - 发送对象想转移的隐私信息的 Keccak256 哈希值。
\end{itemize}

返回：
\begin{itemize}
    \item $String \in \mathbb{B}_{32}$ - 该交易的唯一哈希值，当该交易不合法时将返回空的哈希值（$\mathcal{T}_e \in \mathbb{N}_{32}$）。
\end{itemize}

例子：
\begin{lstlisting}[language=bash]
    # request
    > curl -H 'Content-Type: application/json' --data '
    {
      "jsonrpc":"2.0",
      "id":7,
      "method":"okey_transfer",
      "params":[
        {
          "from":"0x77dfe620dd9f88ad12f8d073f2157bebf8c62c52",
          "to":"0x42ff6b5f7973d4303804ac65294737f713596a35",
          "value":{
            "imei":"0x01dc3bb54c7e738bcd13b6f804059c5642571b6c14b7ebff6e1ee78daaf2de10",
          	"cert":"0x7c1b16802b304761acd81e033c1db5a9721da4b32959e4a8361983cfacacbbec",
          	"adimei":"0x0144bb55167ab332117049e2ccd3d8863d241bcc80f46302310a6d942a90e851",
          	"adcert":"0xce00473e3518f320ba6283b673d54b570b74d2185a9ae390563ad5847a91b84e",
          	"priv":"0x42ff6b5f7973d4303804ac65294737f713596a35"
          }
        }
      ]
    }' http://localhost:8545
    # response
    {
      "jsonrpc":"2.0",
      "id":7,
      "result":"0xec1c3ac301be0cfd8e63b13d007bfce85dd45ec7d19b396be156da52b0ee80c1"
    }
\end{lstlisting}

\vskip1.2cm
\hrule
\vskip1.2cm

%% okey_suicide
\textbf{okey\_suicide}

销毁该账户，并将账户下的所有隐私信息转移到另一个账户上，该操作需要两件设备具有相同类型。

参数：
\begin{itemize}
    \item $from:String \in \mathbb{B}_{20}$ - 发送对象的账户地址；
    \item $to:String \in \mathbb{B}_{20}$ - 接收对象的账户地址；
    \item $imei:String \in \mathbb{B}_{32}$ - 发送对象 IMEI 的 Keccak256 哈希值；
    \item $cert:String \in \mathbb{B}_{32}$ - 发送对象证书的 Keccak256 哈希值；
    \item $adimei:String \in \mathbb{B}_{32}$ - 接收对象 IMEI 的 Keccak256 哈希值；
    \item $adcert:String \in \mathbb{B}_{32}$ - 接收对象证书的 Keccak256 哈希值；
    \item $priv:String \in \mathbb{B}_{20}$ - 发送对象想转移的隐私信息的 Keccak256 哈希值。
\end{itemize}

返回：
\begin{itemize}
    \item $String \in \mathbb{B}_{32}$ - 该交易的唯一哈希值，当该交易不合法时将返回空的哈希值（$\mathcal{T}_e \in \mathbb{N}_{32}$）。
\end{itemize}

例子：
\begin{lstlisting}[language=bash]
    # request
    > curl -H 'Content-Type: application/json' --data '
    {
      "jsonrpc":"2.0",
      "id":8,
      "method":"okey_suicide",
      "params":[
        {
          "from":"0x77dfe620dd9f88ad12f8d073f2157bebf8c62c52",
          "to":"0x42ff6b5f7973d4303804ac65294737f713596a35",
          "value":{
            "imei":"0x01dc3bb54c7e738bcd13b6f804059c5642571b6c14b7ebff6e1ee78daaf2de10",
            "cert":"0x7c1b16802b304761acd81e033c1db5a9721da4b32959e4a8361983cfacacbbec",
            "adimei":"0x0144bb55167ab332117049e2ccd3d8863d241bcc80f46302310a6d942a90e851",
            "adcert":"0xce00473e3518f320ba6283b673d54b570b74d2185a9ae390563ad5847a91b84e",
            "priv":"0xa87a3f428d0032b003cf2d7bfa542efbe28c5800"
          }
        }
      ]
    }' http://localhost:8545
    # response
    {
      "jsonrpc":"2.0",
      "id":8,
      "result":"0x06d4143ace5923e4c56211685d622dbd44f9a06d588a28a90f0c5a74ff35119a"
    }
\end{lstlisting}

\vskip1.2cm
\hrule
\vskip1.2cm

%% okey_verify
\textbf{okey\_verify}

门锁开门验证。

参数：
\begin{itemize}
    \item $from:String \in \mathbb{B}_{20}$ - 验证者（O-Key）的账户地址；
    \item $to:String \in \mathbb{B}_{20}$ - 被验证门锁的账户地址；
    \item $imei:String \in \mathbb{B}_{32}$ - 验证者 IMEI 的 Keccak256 哈希值；
    \item $cert:String \in \mathbb{B}_{32}$ - 验证者证书的 Keccak256 哈希值；
    \item $adimei:String \in \mathbb{B}_{32}$ - 被验证门锁 IMEI 的 Keccak256 哈希值；
    \item $adcert:String \in \mathbb{B}_{32}$ - 被验证门锁证书的 Keccak256 哈希值；
    \item $priv:String \in \mathbb{B}_{20}$ - 验证者的生物信息 Keccak256 哈希值。
\end{itemize}

返回：
\begin{itemize}
    \item $String \in \mathbb{B}_{32}$ - 该交易的唯一哈希值，当该交易不合法时将返回空的哈希值（$\mathcal{T}_e \in \mathbb{N}_{32}$）。
\end{itemize}

例子：
\begin{lstlisting}[language=bash]
    # request
    > curl -H 'Content-Type: application/json' --data '
    {
      "jsonrpc":"2.0",
      "id":1,
      "method":"okey_verify",
      "params":[
        {
          "from":"0x42ff6b5f7973d4303804ac65294737f713596a35",
          "to":"0x77dfe620dd9f88ad12f8d073f2157bebf8c62c52",
          "value":{
            "imei":"0x0144bb55167ab332117049e2ccd3d8863d241bcc80f46302310a6d942a90e851",
            "cert":"0xce00473e3518f320ba6283b673d54b570b74d2185a9ae390563ad5847a91b84e",
            "adimei":"0x01dc3bb54c7e738bcd13b6f804059c5642571b6c14b7ebff6e1ee78daaf2de10",
            "adcert":"0x7c1b16802b304761acd81e033c1db5a9721da4b32959e4a8361983cfacacbbec",
            "priv":"0xa87a3f428d0032b003cf2d7bfa542efbe28c5800"
          }
        },
        "latest"
      ]
    }' http://localhost:8545
    # response
    {
      "jsonrpc":"2.0",
      "id":1,
      "result":true
    }
\end{lstlisting}

\subsection{Internal api}

\end{document}